#pragma once
#include <map>
#include "EpilChunkCode.h"
#include "TCharSupport.h"
#include "EpilObject.h"
#include "EpilTableObject.h"
#include "EpilNilObject.h"
#include "EpilStringObject.h"
#include "EpilBooleanObject.h"
#include "EpilNumberObject.h"
#include "EpilNativeFunctionObject.h"
#include "EpilScriptFunctionObject.h"
#include "EpilScope.h"
#include "EpilException.h"
#include "EpilBooleanManager.h"
#include "EpilNilManager.h"
#include "EpilNumberManager.h"

using namespace std;


class EpilInterpreter
{
public:
	EpilInterpreter();
	~EpilInterpreter();

	EpilScope *							GetCurrentScope() const							{ return m_curScope; }

	void								RunString( const tstring & code );
	void								LoadFile( const tstring & filename );
	void								RunFile( const tstring & filename );

	void								ReleaseObject( EpilObject * obj );

	EpilBooleanObject *					CreateBooleanObject( bool value = false );
	void								ReleaseBooleanObject( EpilBooleanObject * obj );
	EpilNumberObject *					CreateNumberObject( double value = 0.0 );
	void								ReleaseNumberObject( EpilNumberObject * obj );
	EpilStringObject *					CreateStringObject( const tstring & value = t("") );
	void								ReleaseStringObject( EpilStringObject * obj );
	EpilNilObject *						CreateNilObject();
	void								ReleaseNilObject( EpilNilObject * obj );
	EpilTableObject *					CreateTableObject();
	void								ReleaseTableObject( EpilTableObject * obj );
	EpilNativeFunctionObject *			CreateNativeFunctionObject( EpilNativeFunction function = NULL );
	void								ReleaseNativeFunctionObject( EpilNativeFunctionObject * obj );
	EpilScriptFunctionObject *			CreateScriptFunctionObject( const list<tstring> & parameters, const EpilChunkCode * block, bool hasVariousParameters = false );
	void								ReleaseScriptFunctionObject( EpilScriptFunctionObject * obj );

	void								RegisterFunction( const tstring & name, EpilNativeFunction function );

	void								CreateGlobalVariable( const tstring & name );
	void								CreateGlobalVariable( const tstring & name, EpilObject * value );
	EpilObject *						GetGlobalVariable( const tstring & name ) const;
	void								SetGlobalVariable( const tstring & name, EpilObject * value );

	EpilObject *						GetVariable( const tstring & name ) const;
	void								SetVariable( const tstring & name, EpilObject * value );

	void								EnterScope();
	void								EnterFunctionScope( bool hasVariousParameters );
	void								LeaveScope();

	bool								HasVariousParameters() const;
	const EpilObjectVector &			GetVariousParameters() const;
	void								SetVariousParameters( const EpilObjectVector & variousParameters );
	const EpilObjectVector &			GetReturns() const;
	void								SetReturns( const EpilObjectVector & returns );

private:
	map<tstring, EpilChunkCode*>		m_fileChunks;
	EpilScope *							m_curScope;
	EpilScope *							m_globalScope;

	EpilNilManager *					m_nilManager;
	EpilBooleanManager *				m_booleanManager;
	EpilNumberManager *					m_numberManager;
};
